"ui";

ui.layout(
    <frame w="*" h="*" bg="#a0c2ed">
        <canvas id="board" w="{{device.width/2}}px" h="{{device.width/2}}px" layout_gravity="center"/>
    </frame>
)

var pieces = [ //[i][j]
    [0, 0, 0],
    [0, 0, 0],
    [0, 0, 0]
]; //棋子,二维数组,1为圈，2为叉
var pretreatment = [-1, -1]; //预览点，实现下棋拖动效果
var player = random(1, 2); //棋权 1为圈 2为叉，考虑1为玩家，2为电脑

let dig = 0; //正对角线积分
let adig = 0; //反对角线积分
let rows = [0, 0, 0]; //各行积分
let cols = [0, 0, 0]; //各列积分
let step = 0; //步数

const move = (row, col, player) => {
    step++;
    pieces[row][col] = player; //写入棋子数组为了canvas绘画
    let sign = player == 1 ? 1 : -1;
    rows[row] += sign;
    cols[col] += sign;
    if (row == col) dig += sign;
    if (row + col == 3 - 1) adig += sign;
    //游戏结束条件：某行/列/对角之 积分==3/-3 玩家1/玩家2 获胜
    if (rows[row] == 3 || cols[col] == 3 || dig == 3 || adig == 3) return 1; //圈获胜
    if (rows[row] == -3 || cols[col] == -3 || dig == -3 || adig == -3) return 2; //叉获胜
    if (step == 9) return 3; //平局
    return 0;
}

const gameInit = () => {
    pieces = [ //[i][j]
        [0, 0, 0],
        [0, 0, 0],
        [0, 0, 0]
    ];
    pretreatment = [-1, -1];
    dig = 0;
    adig = 0;
    rows = [0, 0, 0];
    cols = [0, 0, 0];
    step = 0;
    player = random(1, 2);
    if (player === 2) { //摇到电脑先手，那就走一手
        let [i, j] = [random(0, 1) ? 2 : 0, random(0, 1) ? 2 : 0]; //先手下四角赢面最大
        move(i, j, 2);
        player = 1;
    }
}

gameInit();

const AI = (net) => { //输入3x3井字棋数组 函数代表的是2 返回最佳位置[i, j]
    let level = [
        [0, 0, 0],
        [0, 0, 0],
        [0, 0, 0]
    ]
    const o2 = 10000; //一个己方活二权值
    const x2 = 1000; //一个对方活二权值
    const x = 10; //一个对方活一权值
    const o = 6; //一个己方活一权值
    const nothing = 4; //一个空行权值

    for (let i = 0; i < 3; i++) {
        for (let j = 0; j < 3; j++) {
            if (net[i][j] != 0) level[i][j] = 0;
            else {
                //横竖两条，每人都有
                //自己活二,,220
                if (((net[0][j] + net[1][j] + net[2][j]) == 4) && (net[0][j] * net[1][j] * net[2][j]) == 0 && ((net[0][j] - 1) * (net[1][j] - 1) * (net[2][j] - 1)) == -1)
                    level[i][j] = level[i][j] + o2;
                if (((net[i][0] + net[i][1] + net[i][2]) == 4) && (net[i][0] * net[i][1] * net[i][2]) == 0 && ((net[i][0] - 1) * (net[i][1] - 1) * (net[i][2] - 1)) == -1)
                    level[i][j] = level[i][j] + o2;
                //对方活二，110
                if (((net[0][j] + net[1][j] + net[2][j]) == 2) && (net[0][j] * net[1][j] * net[2][j]) == 0 && ((net[0][j] - 1) * (net[1][j] - 1) * (net[2][j] - 1)) == 0)
                    level[i][j] = level[i][j] + x2;
                if (((net[i][0] + net[i][1] + net[i][2]) == 2) && (net[i][0] * net[i][1] * net[i][2]) == 0 && ((net[i][0] - 1) * (net[i][1] - 1) * (net[i][2] - 1)) == 0)
                    level[i][j] = level[i][j] + x2;
                //单个X，100
                if (((net[0][j] + net[1][j] + net[2][j]) == 1) && (net[0][j] * net[1][j] * net[2][j]) == 0 && ((net[0][j] - 1) * (net[1][j] - 1) * (net[2][j] - 1)) == 0)
                    level[i][j] = level[i][j] + x;
                if (((net[i][0] + net[i][1] + net[i][2]) == 1) && (net[i][0] * net[i][1] * net[i][2]) == 0 && ((net[i][0] - 1) * (net[i][1] - 1) * (net[i][2] - 1)) == 0)
                    level[i][j] = level[i][j] + x;
                //单个O，200
                if (((net[0][j] + net[1][j] + net[2][j]) == 2) && (net[0][j] * net[1][j] * net[2][j]) == 0 && ((net[0][j] - 1) * (net[1][j] - 1) * (net[2][j] - 1)) == 1)
                    level[i][j] = level[i][j] + o;
                if (((net[i][0] + net[i][1] + net[i][2]) == 2) && (net[i][0] * net[i][1] * net[i][2]) == 0 && ((net[i][0] - 1) * (net[i][1] - 1) * (net[i][2] - 1)) == 1)
                    level[i][j] = level[i][j] + o;
                //空行，000
                if (((net[0][j] + net[1][j] + net[2][j]) == 0) && (net[0][j] * net[1][j] * net[2][j]) == 0 && ((net[0][j] - 1) * (net[1][j] - 1) * (net[2][j] - 1)) == -1)
                    level[i][j] = level[i][j] + nothing;
                if (((net[i][0] + net[i][1] + net[i][2]) == 0) && (net[i][0] * net[i][1] * net[i][2]) == 0 && ((net[i][0] - 1) * (net[i][1] - 1) * (net[i][2] - 1)) == -1)
                    level[i][j] = level[i][j] + nothing;

                //分情况
                //主对角线
                if ((i == 0 && j == 0) || (i == 2 && j == 2) || (i == 1 && j == 1)) {
                    //己方活二
                    if (((net[0][0] + net[1][1] + net[2][2]) == 4) && (net[0][0] * net[1][1] * net[2][2]) == 0 &&
                        ((net[0][0] - 1) * (net[1][1] - 1) * (net[2][2] - 1)) == -1)
                        level[i][j] = level[i][j] + o2;
                    //对方活二
                    if (((net[0][0] + net[1][1] + net[2][2]) == 2) && (net[0][0] * net[1][1] * net[2][2]) == 0 &&
                        ((net[0][0] - 1) * (net[1][1] - 1) * (net[2][2] - 1)) == 0)
                        level[i][j] = level[i][j] + x2;
                    //单个X
                    if (((net[0][0] + net[1][1] + net[2][2]) == 1) && (net[0][0] * net[1][1] * net[2][2]) == 0 &&
                        ((net[0][0] - 1) * (net[1][1] - 1) * (net[2][2] - 1)) == 0)
                        level[i][j] = level[i][j] + x;
                    //单个O
                    if (((net[0][0] + net[1][1] + net[2][2]) == 2) && (net[0][0] * net[1][1] * net[2][2]) == 0 &&
                        ((net[0][0] - 1) * (net[1][1] - 1) * (net[2][2] - 1)) == 1)
                        level[i][j] = level[i][j] + o;
                    //空行，000
                    if (((net[0][0] + net[1][1] + net[2][2]) == 0) && (net[0][0] * net[1][1] * net[2][2]) == 0 &&
                        ((net[0][0] - 1) * (net[1][1] - 1) * (net[2][2] - 1)) == -1)
                        level[i][j] = level[i][j] + nothing;
                }

                //副对角线
                if ((i == 0 && j == 2) || (i == 2 && j == 0) || (i == 1 && j == 1)) {
                    //己方活二
                    if (((net[0][2] + net[1][1] + net[2][0]) == 4) && (net[0][2] * net[1][1] * net[2][0]) == 0 &&
                        ((net[0][2] - 1) * (net[1][1] - 1) * (net[2][0] - 1)) == -1)
                        level[i][j] = level[i][j] + o2;
                    //对方活二
                    if (((net[0][2] + net[1][1] + net[2][0]) == 2) && (net[0][2] * net[1][1] * net[2][0]) == 0 &&
                        ((net[0][2] - 1) * (net[1][1] - 1) * (net[2][0] - 1)) == 0)
                        level[i][j] = level[i][j] + x2;
                    //单个X
                    if (((net[0][2] + net[1][1] + net[2][0]) == 1) && (net[0][2] * net[1][1] * net[2][0]) == 0 &&
                        ((net[0][2] - 1) * (net[1][1] - 1) * (net[2][0] - 1)) == 0)
                        level[i][j] = level[i][j] + x;
                    //单个O
                    if (((net[0][2] + net[1][1] + net[2][0]) == 2) && (net[0][2] * net[1][1] * net[2][0]) == 0 &&
                        ((net[0][2] - 1) * (net[1][1] - 1) * (net[2][0] - 1)) == 1)
                        level[i][j] = level[i][j] + o;
                    //空行，000
                    if (((net[0][2] + net[1][1] + net[2][0]) == 0) && (net[0][2] * net[1][1] * net[2][0]) == 0 &&
                        ((net[0][2] - 1) * (net[1][1] - 1) * (net[2][0] - 1)) == -1)
                        level[i][j] = level[i][j] + nothing;
                } //the end of for if
            } //the end of if
        } //the end of for j
    } //the end of for j


    //寻找最大权值的位置
    let maxi = 0,
        maxj = 0,
        temp = 0;
    for (let i = 0; i < 3; i++) {
        for (let j = 0; j < 3; j++) {
            if (level[i][j] > temp) {
                temp = level[i][j];
                maxi = i;
                maxj = j;
            }
        }
    }
    return [maxi, maxj];
}

const AiGo = () => {
    let [i, j] = AI(pieces);
    let result = move(i, j, 2);
    if (result) {
        toast("游戏结束 " + (result == 1 ? '我真菜' : result == 2 ? '你真菜' : '平局'));
        gameInit()
    }
    player = 1;
}

var paint = new Paint();

//线 #ff00000000 2px
paint.setStyle(Paint.Style.STROKE);
paint.setARGB(0, 0, 0, 255);
paint.setStrokeWidth(2);

ui.board.on("draw", (canvas) => {
    //清空画布
    canvas.drawColor(android.graphics.Color.TRANSPARENT, android.graphics.PorterDuff.Mode.CLEAR)
})
ui.board.on("draw", (canvas) => {
    const [w, h] = [ui.board.getWidth(), ui.board.getHeight()];
    const [x0, y0, dx, dy] = [Math.floor(w / 6), Math.floor(w / 6), Math.floor(w / 3), Math.floor(h / 3)];

    //线 #ff000000 2px
    paint.setStyle(Paint.Style.STROKE);
    paint.setARGB(255, 0, 255, 255);
    paint.setStrokeWidth(2);

    //画网格井字
    canvas.drawLine(dx, 0, dx, 3 * dy, paint);
    canvas.drawLine(2 * dx, 0, 2 * dx, 3 * dy, paint);
    canvas.drawLine(0, dy, 3 * dx, dy, paint);
    canvas.drawLine(0, 2 * dy, 3 * dx, 2 * dy, paint);
    //画网格结束

    //线 #ff000000 10px
    paint.setStrokeWidth(10);

    const drawO = (i, j) => { //画圈 i是y j是x
        let [centerX, centerY, radius] = [x0 + j * dx, y0 + i * dy, x0 - 15];
        canvas.drawCircle(centerX, centerY, radius, paint)
    }

    const drawX = (i, j) => { //画叉 i是y j是x
        let [centerX, centerY] = [x0 + j * dx, y0 + i * dy];
        let [left, top, right, buttom] = [centerX - x0 + 15, centerY - y0 + 15, centerX + x0 - 15, centerY + y0 - 15];
        canvas.drawLine(left, top, right, buttom, paint);
        canvas.drawLine(right, top, left, buttom, paint);
    }

    pieces.forEach((line, i) => { //i是数组外层，是y
        line.forEach((piece, j) => { //j是x
            switch (piece) { //空是0，圈是1，叉是2
                case 0:
                    break;
                case 1:
                    drawO(i, j);
                    break;
                case 2:
                    drawX(i, j);
                    break;
                default:
                    break;
            }
        })
    })
    drawO(pretreatment[0], pretreatment[1]); //画预览
})

ui.board.setOnTouchListener((view, event) => {
    switch (event.getAction()) {
        case event.ACTION_DOWN:
            let [x, y] = [event.getX(), event.getY()];
            let [dx, dy] = [view.getWidth() / 3, view.getHeight() / 3]
            for (let i = 0; i < 3; i++) {
                if (y < i * dy || y >= (i + 1) * dy) {
                    continue;
                }
                for (let j = 0; j < 3; j++) {
                    if (x > j * dx && x < (j + 1) * dx) {
                        if (!pieces[i][j]) {
                            pretreatment = [i, j];
                        }
                        break;
                    }
                }
            }
            break;
        case event.ACTION_MOVE:
            [x, y] = [event.getX(), event.getY()];
            [dx, dy] = [view.getWidth() / 3, view.getHeight() / 3]
            for (let i = 0; i < 3; i++) {
                if (y < i * dy || y >= (i + 1) * dy) {
                    continue;
                }
                for (let j = 0; j < 3; j++) {
                    if (x > j * dx && x < (j + 1) * dx) {
                        if (!pieces[i][j]) {
                            pretreatment = [i, j];
                        }
                        break;
                    }
                }
            }
            break;
        case event.ACTION_UP:
            [x, y] = [event.getX(), event.getY()];
            [dx, dy] = [view.getWidth() / 3, view.getHeight() / 3]
            for (let i = 0; i < 3; i++) {
                if (y < i * dy || y >= (i + 1) * dy) {
                    continue;
                }
                for (let j = 0; j < 3; j++) {
                    if (x > j * dx && x < (j + 1) * dx) {
                        if (!pieces[i][j]) {
                            //因为棋权 [1,2]-[圈,叉]-[1,2] 棋子
                            let result = move(i, j, 1);
                            if (result) {
                                toast("游戏结束 " + (result == 1 ? '你赢了' : result == 2 ? '我赢了' : '平局'));
                                gameInit();
                            } else {
                                AiGo();
                            }
                        }
                        player = 2;
                        break;
                    }
                }
            }
            break
    }
    return true;
})